package com.apes.scm.pur.purchaseOrder.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.plugin.soe.store.database.repository.SceneRepository;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.pi.service.PiManager;
import com.apes.scm.account.account.model.Cooperation;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.repository.TaxRepository;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.account.transit.DepositInTransitService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.masterdata.contrast.model.ContrastPartyCode;
import com.apes.scm.masterdata.contrast.repository.ContrastPartyCodeRepository;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.model.EnumerationType;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.model.SupplierLogistic;
import com.apes.scm.masterdata.party.model.SupplierShipItem;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.party.repository.SupplierLogisticRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.masterdata.product.repository.ProductUomRepository;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import com.apes.scm.masterdata.stock.service.LocationService;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrder;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrderItem;
import com.apes.scm.pur.purchaseOrder.repository.PurchaseOrderItemRepository;
import com.apes.scm.pur.purchaseOrder.repository.PurchaseOrderRepository;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.UserRepository;
import com.apes.scm.stock.transfer.model.Pick;
import com.apes.scm.stock.transfer.model.PickItem;
import com.apes.scm.stock.transfer.repository.PickRepository;
import com.apes.scm.voucher.service.builder.CrossTransferVoucherBuilder;
import com.apes.scm.yy.QueryCommonService;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;



/**
 * 功能：采购订单服务
 *
 * @author xul
 * @create 2018-01-30 11:35
 */
@Service("purchaseService")
public class PurchaseService extends DomainService {
    @Autowired
    private PurchaseOrderRepository orderRepository;
    @Autowired
    private ProductAccountService productAccountService;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private TaxRepository taxRepository;
    @Autowired
    private ContractRepository contractRepository;
    @Autowired
    private LocationService locationService;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private ProductUomRepository productUomRepository;
    @Autowired
    private ContrastPartyCodeRepository contrastPartyCodeRepository;
    @Autowired
    private SceneRepository sceneRepository;
    @Autowired
    private PiManager piManager;
    @Autowired
    private TaxService taxService;
    @Autowired
    private QueryCommonService queryCommonService;
    @Autowired
    private EnumerationRepository enumerationRepository;
    @Autowired
    private OutboxSubscriberService outboxSubscriberService;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private PurchaseOrderItemRepository purchaseOrderItemRepository;
    @Autowired
    private DepositInTransitService depositInTransitService;

    public PurchaseOrder findOne(SimpleRequest request) {
        String id = request.get("id");
        PurchaseOrder order = orderRepository.findOne(id);
        this.sortOrderItem(order.getPurchaseItems());
        return order;
    }

    public Page<PurchaseOrder> findAll(SimpleRequest request) {
        List<Map> filters = request.get("condition");
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        return orderRepository.findAll(JpaDsl.toCriteria(filters), PageRequest.of(request.get("page"), request.get("size"), sort));
    }

    /**
     * 功能：创建采购订单
     *
     * @param request
     * @return
     */
    public PurchaseOrder create(SimpleRequest request) {
        PurchaseOrder order = request.getO(PurchaseOrder.class);
        if (!StringUtils.isEmpty(order.getSupplierRef())) { // 第三方创建订单，不允许重复生成订单
            PurchaseOrder order1 = orderRepository.findOne(JpaDsl.toCriteriaByEq("supplierRef", order.getSupplierRef())).orElse(null);
            if (order1 != null) {
                return null;
            }
        }
        if (order.getCreateUid() == null) order.setCreateUid(this.getPerson(request));
        if (StringUtils.isEmpty(order.getCreator()) && order.getCreateUid() != null) order.setCreator(order.getCreateUid().getId());

        setSuppliterInformation(order);
        findSiteAndAdress(order);
        order = save(order);

        // 需要检查有没有其他地方做了相同修改??????????????
        this.UpdateRequireQty(order, 1);

        return order;
    }


    // 功能：保存采购订单
    public PurchaseOrder save(PurchaseOrder order) {
        order.setState("sent");
        order.setDateOrder(new Date());
        order.setInvoiceStatus("no");
        order.computeAmt(); //汇总
        for (int i = 0; i < order.getPurchaseItems().size(); i++) {
            PurchaseOrderItem item = order.getPurchaseItems().get(i);
            item.setEffectiveQty(item.getProductUomQty()); // 如果其他地方使用 save 方法，则此代码需要挪位
            if (!this.judgeSatisfyRequireDistri(order.getProductRequire(), item.getProduct().getId())) {
                order.getPurchaseItems().remove(item);
                i--;
            }
        }
        if (order.getPurchaseItems().isEmpty()) return new PurchaseOrder();
        order.judgeComapnyGetCooperation();
        PurchaseOrder purchaseOrder = orderRepository.saveAndFlush(order);
        return purchaseOrder;
    }

    // 针对老系统回写订货数量延迟，或要货补货管理数据没有刷新进行补货
    private boolean judgeSatisfyRequireDistri(String requireId, String productId) {
        if (StringUtils.isEmpty(requireId)) return true;
        List<Map> purchaseDistriRequireQty = orderRepository.findAllRequireProQty(requireId, productId);
        if (purchaseDistriRequireQty.isEmpty()) return true;
        double oldPurchaseQty = Double.valueOf(purchaseDistriRequireQty.get(0).get("PURCHASE_QTY").toString());
        double requireQty = Double.valueOf(purchaseDistriRequireQty.get(0).get("REQUIRE_QTY").toString());
        if (oldPurchaseQty >= requireQty) return false;
        return true;
    }

    public void baturuFailCancel(String requireId) {
        PurchaseOrder order = orderRepository.findBaturuPurchaseOrder(requireId);
        order.setState("cancel");
        order.setDateCancel(new Date());
        order.setCancelNameId(partyRoleRepository.findOne("system"));
        order.setNote("巴图鲁推送失败自动终止");
        this.cancelOrder(order);
    }

    public void externalCallSave(PurchaseOrder order) {
        orderRepository.save(order);
    }

    // 修改第三方编码
    public void updateSupplierRef(String supplierRef, String requireId) {
        PurchaseOrder order = orderRepository.findBaturuPurchaseOrder(requireId);
        order.setSupplierRef(supplierRef);
        this.externalCallSave(order);
    }


    // 转OA
    public PurchaseOrder toOA(SimpleRequest simpleRequest) {
        PurchaseOrder order = simpleRequest.getO(PurchaseOrder.class);
        if (order.getToOAUid() == null) {
            order.setToOAUid(simpleRequest.getPerson());
            order.setToOADate(new Date());
        } else { // 店长审批去掉以下两个字段值，方便再次发起转OA
            order.setToOAUid(null);
            order.setToOADate(null);
        }
        orderRepository.saveAndFlush(order);
        return order;
    }


    // 删除
    public String delete(SimpleRequest request) {
        String id = request.get("id");
        PurchaseOrder order = orderRepository.findOne(id);
        if (order == null) throw new RuntimeException("采购订单：" + request.get("id") + " 在系统中不存在。");
        if (order.getDateApprove() != null) throw new RuntimeException("采购订单：" + request.get("id") + " 在系统中已审批。");

        // 还原要货数量及扩展表
        this.UpdateRequireQty(order, -1);

        order.setState("delete");
        order.setDeleteDate(new Date());
        order.setDeletePersonId(request.getPerson());
        orderRepository.saveAndFlush(order);
        return "删除成功！";
    }


    // 终止
    public PurchaseOrder cancel(SimpleRequest request) {
        String id = request.get("id");
        PurchaseOrder order = orderRepository.findOne(id);
//        if (order.getSupplier().getParty().getName().indexOf("巴图鲁") != -1) throw new RuntimeException("巴图鲁供应商订单不允许终止!");
        if (order == null) throw new RuntimeException("采购订单：" + request.get("id") + " 在系统中不存在。");
        if (order.getVersion() != (int) request.get("version")) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        if ("cancel".equals(order.getState())) throw new RuntimeException("采购订单：" + request.get("id") + " 在系统中已取消！");
        if (LogicalUtil.in(order.getSourceType(), "XC0", "ZC0", "ZD0"))  throw new RuntimeException("此单据已发货！不能终止");

        order.setDateCancel(new Date());
        order.setCancelNameId(request.getPerson());
        order = cancelOrder(order); // 取消新系统采购订单
        if ("CD0".equals(order.getSourceType())) {
            JSONObject data = new JSONObject();
            data.put("CGDDH", order.getSource());
            outboxSubscriberService.commonSendRequest("local:purchaseService.cancelOldCGDD", "cancelOldCGDD" + id, data);
        }


        return order;
    }

    // 外部取消
    public void externalCancelCall(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        PurchaseOrder order = orderRepository.findOne(JpaDsl.toCriteriaByEq("supplierRef", getJO.getString("supplierRef"))).orElse(new PurchaseOrder());
        order.setState("cancel");
        order.setCancelNameId(partyRoleRepository.findOne(getJO.getString("operatorName")));
        order.setDateCancel(new Date());

        getJO.getJSONArray("item").forEach(purchaseItem -> {
            JSONObject purchaseItemO = (JSONObject) purchaseItem;

            order.getPurchaseItems().forEach(orderI -> {
                if (orderI.getSourceItemId().equals(purchaseItemO.getString("sourceItemId"))) {
                    orderI.setStopQty(orderI.getStopQty() + purchaseItemO.getDoubleValue("stopQty"));
                    orderI.setEffectiveQty(0);

                    // 删除未达账
                    this.deleteDepositInTransit(orderI.getPurchaseOrder(), orderI.getId());
                }
            });

            orderRepository.saveAndFlush(order);
        });

        // 取消交货单、运单
        this.cancelExpandData(order);

        getJO.put("operate", "供应商订单终止");
        outboxSubscriberService.commonSendRequest("local:supplierOrder.supplierCancelMessageForward", "supplierStopMessageForward: " + order.getId(), getJO);

    }

    private void cancelExpandData(PurchaseOrder order) {
        //取消交货单
        JSONObject tempJson = new JSONObject();
        List<Map> items = this.makeupPick(tempJson, order);
        if (items.size() == 0) return;
        tempJson.put("items", items);
        invoke("stock.pick.cancel", tempJson);

        // 终止运单
        invoke("tms.waybill.repeal", MapUtil.mapper("sourceBusinessKey", order.getId(), "sourceBusinessType", "PurchaseOrder"));
    }




    @OutboxSubscriber(id = "purchaseService.cancelSupplier", name = "取消采购订单回写供应商平台状态与数量")
    private void cancelSupplier(OutboxPayloadWrapper outboxPayloadWrapper){
        invoke("sp.OrderForm.purchaseCancel",outboxPayloadWrapper.getPayload());
    }

    @OutboxSubscriber(id = "local:purchaseService.cancelOldCGDD", name = "终止-终止老系统采购订单")
    private void cancelOldCGDD(OutboxPayloadWrapper outboxPayloadWrapper) {
        piManager.synErp("scmCgddService.updateNewFrameZZ", outboxPayloadWrapper.getPayload());
    }

    public PurchaseOrder baturuCancelOrder(PurchaseOrder order, JSONArray orderDetailList) {
        PurchaseOrder finalOrder = order;
        orderDetailList.forEach(orderDetail -> {
            JSONObject orderDetailObj = (JSONObject) orderDetail;

            finalOrder.getPurchaseItems().forEach(item -> {
                if (item.getStopQty() > 0 && orderDetailObj.getString("priceNo").equals(item.getExternalCode())) {
                    this.deleteDepositInTransit(item.getPurchaseOrder(), item.getId());
//                    productAccountService.setProductRequireBilling(item.getProduct(),
//                            item.getPurchaseOrder().getLocation(), item.getUom(), -1 * item.getStopQty(),
//                            item.getPurchaseOrder().getInnerBusinessType(), item.getPurchaseOrder().getId(), String.valueOf(item.getId()),
//                            "采购订单终止", item.getPurchaseOrder().getCompany(), item.getPurchaseOrder().getProductRequire());

                    // 变更库存要货制单数量, ********【必须先修改要货制单数量，再修改要货分配数量】*********
                    invoke("stock.productRequireService.currentStopQty",
                            MapUtil.mapper(
                                    "requireItemId", item.getSourceItemId(), "uomId", item.getUom().getId(), "qty", item.getStopQty(),
                                    "operateId", finalOrder.getId(), "operateBusinessType", finalOrder.getInnerBusinessType(), "operateItemId", item.getId(),
                                    "operateRemark", "采购订单终止"
                            ));

                    productAccountService.setProductPurchasingWay(item.getProduct(), item.getPurchaseOrder().getLocation(), item.getUom(), -1 * item.getStopQty(), item.getPurchaseOrder().getCompany());
                }
            });
        });


        order = orderRepository.save(order);

        //取消交货单
        JSONObject tempJson = new JSONObject();
        List<Map> items = this.makeupPick(tempJson, order, orderDetailList);
        if (items.size() == 0) return order;
        tempJson.put("items", items);
        invoke("stock.pick.cancel", tempJson);

        // 终止运单
        invoke("tms.waybill.repeal", MapUtil.mapper("sourceBusinessKey", order.getId(), "sourceBusinessType", "PurchaseOrder"));
        return order;
    }

    public PurchaseOrder cancelOrder(PurchaseOrder order) {
        order.getPurchaseItems().forEach(purchaseOrderItem -> {
            double stopQty = purchaseOrderItem.getProductUomQty() - purchaseOrderItem.getQtyReceived();
            purchaseOrderItem.setStopQty(stopQty);
            purchaseOrderItem.setEffectiveQty(0);
            // 删除未达账
            this.deleteDepositInTransit(purchaseOrderItem.getPurchaseOrder(), purchaseOrderItem.getId());

            // 修改订货在途
            productAccountService.setProductPurchasingWay(purchaseOrderItem.getProduct(), purchaseOrderItem.getPurchaseOrder().getLocation(), purchaseOrderItem.getUom(), -stopQty, purchaseOrderItem.getPurchaseOrder().getCompany());

            this.cancelUpdateRequireOrderQtyAndExpand(purchaseOrderItem);

        });

        order.setShipped();
        order = orderRepository.saveAndFlush(order);

        // 取消要货扩展、要货明细表的数据
//        this.cancelUpdateRequireOrderQtyAndExpand(order);

        // 取消运单、交货单
        this.cancelExpandData(order);
        return order;
    }

    // 删除未达账
    private void deleteDepositInTransit(PurchaseOrder order, long itemId) {
        DepositInTransitService depositInTransitService = SpringManager.getBean(DepositInTransitService.class);
        depositInTransitService.delete(order.getInnerBusinessType(), order.getInnerBusinessKey(),
                String.valueOf(itemId), order.getLocation());
    }

    // 拼接交货信息
    private List<Map> makeupPick(JSONObject tempJson, PurchaseOrder order, JSONArray baturuDatas) {
        tempJson.put("id", order.getId());
        tempJson.put("cancelUid", order.getCancelNameId().getId());
        tempJson.put("innerBusinessType", order.getInnerBusinessType());
        List<Map> items = order.getPurchaseItems().stream().filter(purchaseOrderItem -> purchaseOrderItem.getStopQty() > 0).map(purchaseOrderItem -> {
            Map pickItem = new HashMap();
            baturuDatas.forEach(orderDetail -> {
                if (((JSONObject) orderDetail).getString("priceNo").equals(purchaseOrderItem.getExternalCode())) {
                    pickItem.put("id", purchaseOrderItem.getId());
                    pickItem.put("cancelQty", purchaseOrderItem.getStopQty());
                }
            });
            if (pickItem.isEmpty()) return null;
            return pickItem;
        }).collect(Collectors.toList());

        return items;
    }

    // 拼接交货信息
    private List<Map> makeupPick(JSONObject tempJson, PurchaseOrder order) {
        tempJson.put("id", order.getId());
        tempJson.put("cancelUid", order.getCancelNameId().getId());
        tempJson.put("innerBusinessType", order.getInnerBusinessType());
        List<Map> items = order.getPurchaseItems().stream().filter(purchaseOrderItem -> purchaseOrderItem.getStopQty() > 0).map(purchaseOrderItem -> {
            Map pickItem = new HashMap();
            pickItem.put("id", purchaseOrderItem.getId());
            pickItem.put("cancelQty", purchaseOrderItem.getStopQty());
            return pickItem;
        }).collect(Collectors.toList());

        return items;
    }

    /**
     * 外采询价终止, 没有老框架来源数据
     * ???????
     * @param purchaseOrder
     */
    public void cacenlProductRequire(PurchaseOrder purchaseOrder) {
        if (!("ProductRequire".equals(purchaseOrder.getOriginBusinessType()) && StringUtils.isEmpty(purchaseOrder.getSource()))) return;

        JSONObject productRequire = new JSONObject();
        productRequire.put("id", purchaseOrder.getOrigin());
        productRequire.put("repealId", purchaseOrder.getCancelNameId().getId());
        productRequire.put("repealDate", new Date());

        invoke("stock.productRequire.updateQtyArrive", productRequire);

        JSONArray items = new JSONArray();
        purchaseOrder.getPurchaseItems().forEach(purchaseOrderItem -> {
            JSONObject itemObj = new JSONObject();
            itemObj.put("qtyEnd", purchaseOrderItem.getStopQty());
            itemObj.put("remark", "采购订单终止");
            itemObj.put("product_id", purchaseOrderItem.getProduct().getId());
            productRequire.put("oldFrame", 1);
            items.add(itemObj);
        });
        productRequire.put("productRequireItems", items);
        invoke("stock.productRequire.repeal", productRequire);
    }

    // 老框架终止
    public PurchaseOrder stopPurchaseOrder(SimpleRequest request) {
        JSONObject getJo = request.getJO();
        List<PurchaseOrder> purchaseOrderList = orderRepository.findAll(JpaDsl.toCriteriaByEq("supplierRef", getJo.getString("CGDDH"), "state", "confirmed"));
        PurchaseOrder purchaseOrder = purchaseOrderList.get(0);
        if (purchaseOrder.getDateCancel() != null) throw new RuntimeException("采购订单：" + purchaseOrder.getId() + " 在系统中已取消。");
        purchaseOrder.setState("cancel");
        purchaseOrder.setDateCancel(new Date());
        purchaseOrder.setCancelNameId(partyRoleRepository.findOne(getJo.getString("ZFRID")));
        purchaseOrder.setUserId(SpringManager.getBean(UserRepository.class).findOne(JpaDsl.toCriteriaByEq("person.id", purchaseOrder.getCancelNameId().getId())).get().getId() + "");
        this.cancelOrder(purchaseOrder);
//        this.cancelUpdateRequireOrderQtyAndExpand(purchaseOrder);
        return orderRepository.saveAndFlush(purchaseOrder);
    }



    // 激活
    public PurchaseOrder activationPurchaseOrder(SimpleRequest request) {
        PurchaseOrder order = request.getO(PurchaseOrder.class);
        if ("ProductRequire".equals(order.getOriginBusinessType()) && StringUtils.isEmpty(order.getSource())) throw new RuntimeException("要货外采询价终止不允许激活!");
        if (!"cancel".equals(order.getState())) throw new RuntimeException("不是终止状态, 不存在可激活单据!");
        order.setState("confirmed");
        order.setActivationDate(new Date());
        order.setActivationPeopleId(request.getPerson());
        this.updateActivationQty(order);
        order = orderRepository.saveAndFlush(order);
        Object pick = invoke("purchase.flow.pick", MapUtil.mapped(order));
        invoke("stock.pick.create", MapUtil.mapped(pick));
        return order;
    }


    // 激活修改数量
    private void updateActivationQty(PurchaseOrder purchaseOrder) {
        purchaseOrder.getPurchaseItems().forEach(purchaseOrderItem -> {
            purchaseOrderItem.setEffectiveQty(purchaseOrderItem.getStopQty());
            purchaseOrderItem.setStopQty(0);
        });
    }


    // 审批
    public PurchaseOrder approve(SimpleRequest request) {
        PurchaseOrder order = orderRepository.findOne((String) request.get("id"));
        if (order == null) throw new RuntimeException("采购订单：" + request.get("id") + " 在系统中不存在。");
        if (order.getVersion() != (int) request.get("version")) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        if (order.getDateApprove() != null) throw new RuntimeException("采购订单：" + request.get("id") + " 在系统中已审批。");
        if (order.getApproveUid() == null) order.setApproveUid(request.getPerson());

        order.setShipped();
        order.setState("confirmed");
        order.setDateApprove(new Date());

        List<Map> requireDatas = new ArrayList<>();
        order.getPurchaseItems().forEach(item -> {
            if (LogicalUtil.notIn(item.getProduct().getType(), "aut")) { // 未达账
                double occurQty = productAccountService.computeQtyUnit(item.getPurchaseOrder().getCompany(), item.getProduct(), item.getUom(), item.getProductUomQty());
                Dept receivingDept = null;

                if (item.getPurchaseOrder().getReceiptLocation() != null) receivingDept = item.getPurchaseOrder().getReceiptLocation().getDepot().getDept();
                depositInTransitService.save(item.getPurchaseOrder().getCompany(), item.getPurchaseOrder().getLocation(), receivingDept, item.getPurchaseOrder().getInnerBusinessType(), item.getPurchaseOrder().getInnerBusinessKey(),
                        String.valueOf(item.getId()), item.getProduct(), occurQty, "收货");
            }

            // 订货在途、期初入库写收货数量、要货扩展表、要货订货数量、要货分配数量
            Map requireData = this.changeAboutDocumentData(item, item.getPurchaseOrder());
            if (!requireData.isEmpty()) requireDatas.add(requireData);
        });

        if ("PO002".equals(order.getScene().getId())) order.setShipped(true);
        if (!requireDatas.isEmpty()) {
            invoke("stock.productRequireService.updateAssignmentQtyAndOrderQty", MapUtil.mapper("id", order.getProductRequire(), "distributionId", order.getId(), "item", requireDatas));
        }

        // 期初入库回写收货数量
       /* this.earlyStorageNumber(order);

        // 修改要货订货数量、要货扩展表
        this.confirmUpdateRequireOrderQtyAndExpand(order);


        // 订货在途
        this.addProductPurchasingWayQty(order);

        // 未达帐
        saveDepositInTransit(order);*/
        order = orderRepository.saveAndFlush(order);

        // 生成交货单  排除期初入库
        this.sendProducePick(order.getId(), order);

        return order;
    }

    public Map changeAboutDocumentData(PurchaseOrderItem orderItem, PurchaseOrder order) {
        // 期初入库回写收货数量
        if ("PO002".equals(order.getScene().getId())) {
            orderItem.delivery(orderItem.getProductUomQty());
            return new HashMap();
        }

        // 1. 供应商平台过来的订单已提前写入订货在途及要货制单梳理
        if (!StringUtils.isEmpty(order.getSupplierType()) && LogicalUtil.in(order.getSupplierType(), "santou", "supplier")) return new HashMap();

        // 2. 普通采购订单审核：修改订货在途
        productAccountService.setProductPurchasingWay(orderItem.getProduct(), order.getLocation(), orderItem.getUom(), orderItem.getProductUomQty(), order.getCompany());

        // 3. 非供应商平台订单要货生成采购订单需要继续往下走
        if (StringUtils.isEmpty(order.getProductRequire()) || StringUtils.isEmpty(orderItem.getSourceItemId())) return new HashMap();

        // 变更库存要货制单数量, ********【必须先修改要货制单数量，再修改要货分配数量】*********
        invoke("stock.productRequireService.currentAssigentQty",
                MapUtil.mapper(
                        "requireItemId", orderItem.getSourceItemId(), "uomId", orderItem.getUom().getId(), "qty", orderItem.getProductUomQty(),
                        "operateId", order.getId(), "operateBusinessType", order.getInnerBusinessType(), "operateItemId", orderItem.getId(),
                        "operateRemark", "采购订单审核"
                ));

        // 生成要货扩展表
        JSONObject requireAllQty = this.obtainRequireQty(orderItem);
        this.sendRequireExpandData(order.getProductRequire(), order.getId(), order.getSourceType(), orderItem, requireAllQty.getDoubleValue("qtyRequire"));

        // 拼接要货数据
        return MapUtil.mapper("orderQty", -1 * orderItem.getProductUomQty(), "qtyAssigned", orderItem.getProductUomQty(), "id", orderItem.getSourceItemId());
    }
    

    @Listener(topic = "event:stock.pick.delivery")
    public void purchaseReceipt(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        PurchaseOrder purchaseOrder = orderRepository.findOne(getJO.getString("origin"));
        if (purchaseOrder == null) return;
        getJO.getJSONArray("items").forEach(pickItem -> {
            JSONObject pickItemO = (JSONObject) pickItem;
            for (PurchaseOrderItem orderItem : purchaseOrder.getPurchaseItems()) {
                if (orderItem.getId() == pickItemO.getLong("originItemId")) {
                    double receiptQty = orderItem.getQtyReceived() + pickItemO.getDoubleValue("qtyDone");
                    if (receiptQty > orderItem.getProductUomQty()) throw new RuntimeException("接收数量不允许大于订单数量！");
                    orderItem.setQtyReceived(receiptQty);
                    productAccountService.setProductPurchasingWay(orderItem.getProduct(), purchaseOrder.getLocation(),
                            orderItem.getUom(),-1 * pickItemO.getDoubleValue("qtyDone"), purchaseOrder.getCompany());
                    break;
                }
            }
        });
        purchaseOrder.setShipped();
        purchaseOrder.setLastUpdatedStamp(new Date());
        orderRepository.saveAndFlush(purchaseOrder);
    }

     // 发送事务发件箱 生成交货单
     private void sendProducePick(String id, PurchaseOrder order) {
         if (order.getScene().getId().equals("PO002") /*|| order.getSupplier().getName().indexOf("巴图鲁") != -1*/) return;
         JSONObject condi = new JSONObject();
         condi.put("id", id);
         outboxSubscriberService.commonSendRequest("local:PurchaseService.pickOutbox", id, condi);
     }

    @OutboxSubscriber(id = "local:PurchaseService.pickOutbox", name = "采购生成交货单")
    public void pickOutbox(OutboxPayloadWrapper content) {
        JSONObject payloadCon = JSONObject.parseObject(content.getPayload());
        PurchaseOrder order = orderRepository.findOne(payloadCon.getString("id"));
        invoke("stock.pick.create", MapUtil.mapped(purchaseConverPick(order)));
    }

    private Pick purchaseConverPick(PurchaseOrder order, List<PurchaseOrderItem> orderItem, JSONObject otherInfo) {
        Pick pick = new Pick();
        pick.setOperation("receipt");
        pick.setOrigin(order.getId());
        pick.setOriginBusinessType(order.getInnerBusinessType());
        pick.setCompany(order.getCompany());
        pick.setPartner(order.getSupplier());
        pick.setLocation(order.getLocation());
        pick.setCreator(order.getApproveUid().getId());
        pick.setSupplierPartyB(otherInfo.getString("supplierId"));
        pick.setSupplierNamePartyB(otherInfo.getString("supplierName"));
        pick.setParcelListNo(otherInfo.getString("trackingNumber"));
        if (Objects.nonNull(order.getReceiptLocation())) pick.setReceiptLocation(order.getReceiptLocation());
        pick.setMoveType(order.getMoveType());
        pick.setScene(order.getScene());
        Set<PickItem> items = new HashSet<>();
        orderItem.forEach(purchseItem -> {
            otherInfo.getObject("priceNos", List.class).forEach(priceNoM -> {
                ((Map) priceNoM).forEach((k, v) -> {
                    if (!k.toString().equals(purchseItem.getExternalCode())) return;
                    double num = Double.valueOf(v.toString());
                    PickItem item = new PickItem();
                    item.setOriginLine(String.valueOf(purchseItem.getId()));
                    item.setProduct(purchseItem.getProduct());
                    item.setUom(purchseItem.getUom());

                    double effectiveQty = purchseItem.getProductUomQty() - purchseItem.getQtyReceived() - purchseItem.getStopQty();
                    double pickNum = num > effectiveQty?effectiveQty:num;
                    item.setOrderedQty(pickNum);
                    item.setProductUomQty(pickNum);

                    items.add(item);
                    pick.setPickItems(items);
                });
            });
        });
        return pick;
    }


    // 生成交货单数据转换
    private Pick purchaseConverPick(PurchaseOrder order) {
        Pick pick = new Pick();
        pick.setCustomerExpandId(order.getCustomerExpandId());
        pick.setOperation("receipt");
        pick.setOrigin(order.getId());
        pick.setOriginBusinessType(order.getInnerBusinessType());
        pick.setCompany(order.getCompany());
        pick.setPartner(order.getSupplier());
        pick.setLocation(order.getLocation());
        pick.setCreator(order.getApproveUid().getId());
        if (Objects.nonNull(order.getReceiptLocation())) pick.setReceiptLocation(order.getReceiptLocation());
        pick.setMoveType(order.getMoveType());
        pick.setScene(order.getScene());
        Set<PickItem> items = new HashSet<>();
        order.getPurchaseItems().forEach(purchseItem -> {
            PickItem item = new PickItem();
            item.setOriginLine(String.valueOf(purchseItem.getId()));
            item.setProduct(purchseItem.getProduct());
            item.setUom(purchseItem.getUom());

            double effectiveQty = purchseItem.getProductUomQty() - purchseItem.getQtyReceived() - purchseItem.getStopQty();
            item.setOrderedQty(effectiveQty);
            item.setProductUomQty(effectiveQty);

            items.add(item);
            pick.setPickItems(items);
        });
        return pick;
    }

    // 期初入库回写收货数量
    private void earlyStorageNumber(PurchaseOrder purchaseOrder) {
        if (!"PO002".equals(purchaseOrder.getScene().getId())) return;
        purchaseOrder.getPurchaseItems().forEach(purchaseOrderItem -> {
            purchaseOrderItem.delivery(purchaseOrderItem.getProductUomQty());
        });
        purchaseOrder.setShipped(true);
    }


    // 未达帐
    public void saveDepositInTransit(PurchaseOrder order) {
        DepositInTransitService depositInTransitService = SpringManager.getBean(DepositInTransitService.class);
        ProductAccountService productAccountService = SpringManager.getBean(ProductAccountService.class);
        order.getPurchaseItems().stream()
                .filter(orderItem -> LogicalUtil.notIn(orderItem.getProduct().getType(), "aut"))
                .forEach(item -> {
                    double occurQty = productAccountService.computeQtyUnit(order.getCompany(), item.getProduct(), item.getUom(), item.getProductUomQty());
                    Dept receivingDept = null;
                    if (order.getReceiptLocation() != null) receivingDept = order.getReceiptLocation().getDepot().getDept();
                    depositInTransitService.save(order.getCompany(), order.getLocation(), receivingDept, order.getInnerBusinessType(), order.getInnerBusinessKey(),
                            String.valueOf(item.getId()), item.getProduct(), occurQty, "收货");
                });
    }


    // 延期 - 待使用
    public void delayPurchaseOrder(SimpleRequest request) {
        JSONObject getJo = request.getJO();
        List<PurchaseOrder> purchaseOrderList = orderRepository.findAll(JpaDsl.toCriteriaByEq("supplierRef", getJo.getString("CGDDH")));
        PurchaseOrder purchaseOrder = purchaseOrderList.get(0);
        purchaseOrder.setState("delay");
        orderRepository.saveAndFlush(purchaseOrder);
    }



    // 增加库存帐采购在途
    public PurchaseOrder addProductPurchasingWayQty(PurchaseOrder order) {
        if (order.getScene().getId().equals("PO002")) return order;
        String productRequireId = order.getProductRequire();

        // 写入库存数量处理
        order.getPurchaseItems().forEach((item) -> {
            if (!StringUtils.isEmpty(productRequireId)) {
                this.updateInventoryNumber(order, item, productRequireId, "single", 0, null);

            } else {
                this.updateInventoryNumber(order, item, "", "single", 0, null);
            }
        });
        return order;
    }

    /**
     *
     * @param order
     * @param item
     * @param requireId
     * @param requireAssignType 是否批量分配的要货单
     *                          single: 正常要货, batchRequire: 批量分配数量的要货单
     * @param requireNumber
     * @param appendProductId 用来判断是否要增加在途
     */
    private void updateInventoryNumber(PurchaseOrder order, PurchaseOrderItem item, String requireId, String requireAssignType, double requireNumber, AtomicReference appendProductId) {
        if (!StringUtils.isEmpty(order.getSupplierType()) && LogicalUtil.in(order.getSupplierType(), "santou", "supplier")) return;
        String remarks = "采购订单审核";
        double purchaseWayNumber = 0;
        if ("cancel".equals(order.getState()) && "batchRequire".equals(requireAssignType)) {
            purchaseWayNumber = -1 * item.getStopQty();
            remarks = "采购订单终止";

        } else if ("cancel".equals(order.getState()) && "single".equals(requireAssignType)) {
            requireNumber = item.getStopQty();
            if (requireNumber == 0) return;
            purchaseWayNumber = -1 * item.getStopQty();
            remarks = "采购订单终止";
            if (requireNumber <= 0) throw new RuntimeException(item.getProduct().getName() + " 商品终止数量为" + item.getStopQty() + ", 不能终止, 请检查数据!");

        } else if ("confirmed".equals(order.getState()) && "single".equals(requireAssignType)) {
            requireNumber = (item.getProductUomQty() - item.getQtyReceived()) * -1;
            purchaseWayNumber = item.getProductUomQty();

        } else if ("confirmed".equals(order.getState()) && "batchRequire".equals(requireAssignType)) {
            requireNumber = requireNumber * -1;
            purchaseWayNumber = item.getProductUomQty();
        }

        // 相同商品重复不增加在途
        if (appendProductId == null || appendProductId.get() == null ||
                (appendProductId.get() != null && appendProductId.get().toString().indexOf(";" + item.getProduct().getId() + ';') == -1) || StringUtils.isEmpty(item.getSourceItemId()))
            productAccountService.setProductPurchasingWay(item.getProduct(), order.getLocation(), item.getUom(), purchaseWayNumber, order.getCompany());

        if (StringUtils.hasText(requireId) && StringUtils.isEmpty(item.getSourceItemId())) {
            invoke("stock.productRequireService.currentStopQty",
                    MapUtil.mapper(
                            "requireItemId", item.getSourceItemId(), "uomId", item.getUom().getId(), "qty", Math.abs(requireNumber),
                            "operateId", order.getId(), "operateBusinessType", order.getInnerBusinessType(), "operateItemId", item.getId(),
                            "operateRemark", remarks
                    ));
        }

    }



    // 期初 - 增加可卖数、保管数，通过场景流
    public PurchaseOrder addProductAvailableAndCustody(SimpleRequest request) {
        PurchaseOrder purchaseOrder = request.getO(PurchaseOrder.class);
        purchaseOrder.getPurchaseItems().forEach(
                (purchaseOrderItem) -> {
                    //写商品库存帐可用数
                    productAccountService.setProductAvailable(purchaseOrderItem.getProduct(), purchaseOrder.getLocation(), purchaseOrderItem.getUom(), purchaseOrderItem.getProductUomQty(), PurchaseOrder.class.getSimpleName(), purchaseOrder.getId(), String.valueOf(purchaseOrderItem.getId()), "期初采购", purchaseOrder.getCompany());
                    //写商品库存帐保管数
                    productAccountService.setProductCustody(purchaseOrderItem.getProduct(), purchaseOrder.getLocation(), purchaseOrderItem.getUom(), purchaseOrderItem.getProductUomQty(), PurchaseOrder.class.getSimpleName(), purchaseOrder.getId(), String.valueOf(purchaseOrderItem.getId()), "期初采购", purchaseOrder.getCompany());
                }
        );
        return purchaseOrder;
    }



    // 期初 - 更新完成状态
    public PurchaseOrder setDone(SimpleRequest request) {
        PurchaseOrder purchaseOrder = request.getO(PurchaseOrder.class);
        purchaseOrder.setState("done");
        // 期初入库更新收货数量
        if ("PO002".equals(purchaseOrder.getScene().getId())) {
            purchaseOrder.getPurchaseItems().forEach(purchaseOrderItem -> {
                purchaseOrderItem.setQtyReceived(purchaseOrderItem.getProductUomQty());
            });
        }
        return orderRepository.saveAndFlush(purchaseOrder);
    }


    // 老系统 ---> 新系统 格式化
    public PurchaseOrder formatPurchaseOrder(SimpleRequest request) {
        JSONObject getJo = request.getJO();
        PurchaseOrder purchaseOrder = new PurchaseOrder();

        List<PartyRole> partyRoleList = partyRoleRepository.findAll(JpaDsl.toCriteriaByEq("id", getJo.getString("GSID"), "role.id", "Company"));
        if (partyRoleList.size() == 0) {
            throw new RuntimeException("请定义对应的主数据，公司编码：" + getJo.getString("GSID"));
        }
        purchaseOrder.setCompany(partyRoleList.get(0));

        PartyRole partyRole = new PartyRole();
        partyRole = new PartyRole();
        partyRoleList = partyRoleRepository.findAll(JpaDsl.toCriteriaByEq("id", getJo.getString("RYID"), "role.id", "Employee"));
        if (partyRoleList.size() == 0) {
            throw new RuntimeException("请定义对应的主数据，人员：" + getJo.getString("RYID"));
        }
        partyRole = partyRoleList.get(0);
        purchaseOrder.setClerk(partyRole);

        Contract contract = contractRepository.findOne(getJo.getString("CGHTH"));
        if (contract == null) {
            throw new RuntimeException("未找到相关采购合同！");
        }
        purchaseOrder.setContract(contract);

        String operation = invoke("purchase.order.getModel", MapUtil.mapper("companyId", getJo.getString("GSID")));
        if ("empower".equals(operation)) {
            purchaseOrder.setDept(deptRepository.findAll(JpaDsl.toCriteriaByEq("company.id", getJo.getString("GSID"), "deptType.id", "000006")).get(0));
        } else {
            purchaseOrder.setDept(contract.getDept());
        }

        // 获取要货单
        if (getJo.get("YHDH") != null) {
            Object productRequire = this.invoke("stock.productRequire.findOne", MapUtil.mapper("id", getJo.get("YHDH")));
            if (productRequire == null) throw new RuntimeException("未找到对应的要货单，要货单号：" + getJo.get("YHDH"));
            purchaseOrder.setProductRequire(getJo.getString("YHDH"));

            String fnCustomerId = invoke("stock.productRequire.accordIdFindFnCustomerId", MapUtil.mapper("id", getJo.getString("YHDH")));
            purchaseOrder.setCustomerExpandId(fnCustomerId);
        }

        List<ContrastPartyCode> contrastPartyCodeList = contrastPartyCodeRepository.findAll(JpaDsl.toCriteriaByEq("gysid", getJo.getString("GYSID")));
        if (contrastPartyCodeList.size() == 0) {
            throw new RuntimeException("请配置角色对照表！");
        }
        partyRoleList = partyRoleRepository.findAll(JpaDsl.toCriteriaByEq("party", contrastPartyCodeList.get(0).getParty().getId(), "role.id", "Supplier"));

        if (partyRoleList.size() == 0) {
            throw new RuntimeException("请定义对应的主数据，供应商：" + getJo.getString("GYSMC"));
        }
        partyRole = partyRoleList.get(0);
        purchaseOrder.setSupplier(partyRole);
        if ("004465".equals(purchaseOrder.getSupplier().getId())) {
            purchaseOrder.setScene(sceneRepository.findOne("PO003"));
        } else {
            purchaseOrder.setScene(sceneRepository.findOne("PO001"));
        }

        Enumeration enumeration = new Enumeration();
        EnumerationType enumerationType = new EnumerationType();
        enumerationType.setId("moveType");
        enumeration.setId("direct");
        enumeration.setDescription("部分交货");
        enumeration.setType(enumerationType);
        purchaseOrder.setMoveType(enumeration);

        Location location = locationService.queryTypeSal(request);
        purchaseOrder.setLocation(location);
        purchaseOrder.setAmtTotal(getJo.getDouble("DHZJE"));

        partyRole = new PartyRole();
        List<PartyRole> partyRoleList2 = partyRoleRepository.findAll(JpaDsl.toCriteriaByEq("id", getJo.getString("CKGSID"), "role.id", "Company"));
        if (partyRoleList2.size() == 0) {
            throw new RuntimeException("请定义对应的主数据，公司编码：" + getJo.getString("GSID"));
        }
        partyRole = partyRoleList2.get(0);
        purchaseOrder.setDestAddress(partyRole);

        // 设置上游单据
        purchaseOrder.setOrigin(getJo.getString("ORIGIN"));
        purchaseOrder.setOriginBusinessType(getJo.getString("ORIGIN_BUSINESS_TYPE"));

        // 设置来源单据号码
        purchaseOrder.setSource(getJo.getString("CGDDH"));
        purchaseOrder.setSourceType(getJo.getString("DJLXID"));

        // 设置第三方单据
        purchaseOrder.setSupplierRef(getJo.getString("CGDDH"));
        purchaseOrder.setSupplierType(getJo.getString("DJLXID"));

        Cooperation cooperation = new Cooperation();
        String eHZFS = getJo.getString("HZFS");
        if ("0".equals(eHZFS) || "3".equals(eHZFS)) {
            cooperation.setId("distribution");
            cooperation.setName("经销");
        } else if ("1".equals(eHZFS) || "2".equals(eHZFS)) {
            cooperation.setId("consignment");
            cooperation.setName("代销");
        }
        purchaseOrder.setCarLicense(getJo.getString("CPHM"));
        purchaseOrder.setCooperation(cooperation);
        purchaseOrder.setNote(getJo.getString("BZ"));
        purchaseOrder.setCreator(getJo.getString("SHRID"));
        purchaseOrder.setCreateDate(getJo.getDate("SHRQ_SJ"));

        partyRole = partyRoleRepository.findOne(getJo.getString("SHRID"));
        purchaseOrder.setApproveUid(partyRole);
        purchaseOrder.setDateApprove(getJo.getDate("SHRQ_SJ"));
        purchaseOrder.setDatePlanned(new Date());
        purchaseOrder.setSiteId(getJo.getString("ZDID"));

        int pDJZT = getJo.getInteger("DJZT");
        if (pDJZT == 0) {
            purchaseOrder.setState("sent");
        } else if (pDJZT == 10) {
            purchaseOrder.setState("confirmed");
        } else if (pDJZT == 20) {
            partyRole = partyRoleRepository.findOne(getJo.getString("ZFRID"));
            purchaseOrder.setCancelNameId(partyRole);
            purchaseOrder.setDateCancel(getJo.getDate("ZFRQ_SJ"));
            purchaseOrder.setState("cancel");
        } else if (pDJZT == 30) {
            partyRole = partyRoleRepository.findOne(getJo.getString("JHRID"));
            purchaseOrder.setDelayPeopleId(partyRole);
            purchaseOrder.setDelayDate(getJo.getDate("JHRQ_SJ"));
            purchaseOrder.setState("delay");
        }

        List<PurchaseOrderItem> purchaseOrderItemSet = new ArrayList<>();
        JSONArray CGDDMXItem_Array = getJo.getJSONArray("PUR_CGDDMX");
        for (int i = 0, iLen = CGDDMXItem_Array.size(); i < iLen; i++) {
            JSONObject CGDDMXItem_Obj = CGDDMXItem_Array.getJSONObject(i);
            int hyzt = CGDDMXItem_Obj.getIntValue("HYZT");
            PurchaseOrderItem purchaseOrderItem = new PurchaseOrderItem();
            purchaseOrderItem.setPurchaseOrder(purchaseOrder);
            purchaseOrderItem.setName(CGDDMXItem_Obj.getString("ZY"));
            purchaseOrderItem.setPriceUnit(CGDDMXItem_Obj.getDoubleValue("DHDJ"));
            purchaseOrderItem.setProductUomQty(CGDDMXItem_Obj.getDoubleValue("DHJS"));
            purchaseOrderItem.setDemandQty(CGDDMXItem_Obj.getDoubleValue("YDHJS"));
            purchaseOrderItem.setPriceCeiling(CGDDMXItem_Obj.getDoubleValue("ZGXJ"));
            purchaseOrderItem.setEffectiveQty(purchaseOrderItem.getProductUomQty());
            purchaseOrderItem.setSourceItemId(CGDDMXItem_Obj.getString("XH"));

            List<ProductUom> productUomList = productUomRepository.findAll(JpaDsl.toCriteriaByEq("uomCategory.id", CGDDMXItem_Obj.getString("SPID"), "name", CGDDMXItem_Obj.getString("JLDW")));
            if (productUomList.size() == 0) {
                throw new RuntimeException("请检查计量单位！商品编码" + CGDDMXItem_Obj.getString("SPID"));
            }
            ProductUom productUom = productUomList.get(0);
            purchaseOrderItem.setUom(productUom);

            if (hyzt == 0) {
                purchaseOrderItem.setSourceState(enumerationRepository.findOne("001253"));
            } else if (hyzt == 1) {
                purchaseOrderItem.setSourceState(enumerationRepository.findOne("003334"));
            } else if (hyzt == 2) {
                purchaseOrderItem.setSourceState(enumerationRepository.findOne("003335"));
            }

            Tax tax = new Tax();
            tax = this.formatTax(CGDDMXItem_Obj, tax);
            purchaseOrderItem.setTax(tax);

            purchaseOrderItem.setProduct(productRepository.findOne(CGDDMXItem_Obj.getString("SPID")));

            purchaseOrderItem.setStopQty(CGDDMXItem_Obj.getDoubleValue("ZXJS"));
            purchaseOrderItem.setQtyInvoiced(0);
            purchaseOrderItem.setQtyReceived(CGDDMXItem_Obj.getDoubleValue("RKJS"));
            purchaseOrderItem.computeAmt();
            purchaseOrderItemSet.add(purchaseOrderItem);
        }
        purchaseOrder.setPurchaseItems(purchaseOrderItemSet);
        return purchaseOrder;
    }

    /**
     * 老系统调用 - 保存采购订单
     *
     * @param request
     */
    public PurchaseOrder synPurchaseOrderCreate(SimpleRequest request) {
        PurchaseOrder purchaseOrder = this.formatPurchaseOrder(request);

        if (StringUtils.hasText(purchaseOrder.getProductRequire())) {
            Map requireData = invoke("stock.productRequire.accordIdFindOne", MapUtil.mapper("id", purchaseOrder.getProductRequire()));
            purchaseOrder.setOrigin(requireData.get("source").toString());
            purchaseOrder.setOriginBusinessType(requireData.get("sourceBusinessType").toString());
            purchaseOrder.setOriginBusinessType(requireData.get("sourceBusinessTypeName").toString());
        }
        List<User> userInfo = SpringManager.getBean(UserRepository.class).findAll(JpaDsl.toCriteriaByEq("person.id", purchaseOrder.getCreator()));
        if (userInfo.size() != 0) purchaseOrder.setUserId(userInfo.get(0).getId().toString());
        purchaseOrder = save(purchaseOrder);

        PurchaseOrder order = orderRepository.findOne(purchaseOrder.getId());
        order.setShipped();
        order.setState("confirmed");

        this.confirmUpdateRequireOrderQtyAndExpand(order);

        // 在途
        this.addProductPurchasingWayQty(order);

        // 生成交货单
        this.sendProducePick(order.getId(), order);
        return orderRepository.saveAndFlush(order);

    }

    /**
     * 格式化税率
     *
     * @param param
     * @param tax
     * @return
     */
    private Tax formatTax(JSONObject param, Tax tax) {
        String iSSLBMC = param.getString("SSLBID");
        List<Tax> taxList = taxRepository.findAll(JpaDsl.toCriteriaByEq("origin", iSSLBMC));
        if (taxList.size() == 0) {
            throw new RuntimeException("税率转换失败, 税率名称：" + iSSLBMC);
        }
        return taxList.get(0);
    }

    // 根据单位换算单价
    public Map uomChangePrice(SimpleRequest simpleRequest) {
       Map getMap = simpleRequest.getMap();
        double price = Double.parseDouble(getMap.get("priceUnit") + "");
        ProductUom currentUom = productUomRepository.findOne(Long.parseLong(getMap.get("uomId") + ""));
        ProductUom oldUom = productUomRepository.findOne(Long.parseLong(getMap.get("oldUomId") + ""));
        if (currentUom.getId() != oldUom.getId()) {
            price = Math.round(oldUom.computePrice(price, currentUom));
        }

        Map getPriceParam = new HashMap();
        getPriceParam.put("SYS_RQ", new Date());
        getPriceParam.put("conditionStrategyId", "CG05");
        getPriceParam.put("COMPANY_ID", getMap.get("platformId"));
        Object resultPrice = invoke("condition.execConditionStrategy", getPriceParam);
        JSONObject resultPriceObj = new JSONObject(MapUtil.mapped(resultPrice));
        double newPriceCeiling = price *  (1 + resultPriceObj.getDoubleValue("P002"));
        return MapUtil.mapper("priceCeiling", newPriceCeiling, "priceUnit", price);
    }


    /**
     *获取采购价格策略--新系统
     *@param companyId 采购平台公司编码
     *@param supplierId 供应商编码
     *@param productId 商品编码
     *@param carLicense 车牌号码
     *@return
     */
    public JSONObject getPurcherPrice(String companyId, String supplierId, String productId, String carLicense){
        JSONObject condi = new JSONObject();
        Product product = productRepository.findOne(productId);
        condi.put("SYS_RQ", new Date());
        condi.put("conditionStrategyId", "CG02");
        condi.put("COMPANY_ID", companyId);
        condi.put("SUPPLIER_ID", supplierId);
        condi.put("PRODUCT_ID", productId);
        condi.put("BRAND_ID", product.getBrand().getId());
        condi.put("CLASSIFY_ID", product.getClassify().getId());
        if (!StringUtils.isEmpty(carLicense)) {
            condi.put("CAR_LICENSE", carLicense);
        } else {
            condi.put("SYS_NO_CHECK", "CAR_LICENSE");
        }
        Object obj = this.invoke("condition.execConditionStrategy_trans", condi);
        JSONObject result = new JSONObject(MapUtil.mapped(obj));
        return result;
    }



    // 查询采购合同
    public Page<Map> getContract(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        JSONObject group = getJO.getJSONObject("group");
        JSONObject domain = getJO.getJSONObject("domain");
        JSONArray filters = group != null?group.getJSONArray("filters"):domain != null?domain.getJSONArray("filters"):new JSONArray();

        // 额外的条件
        Map condi = new HashMap();
        condi.put("type", "handPurchaseOrder");
        filters.forEach(filter -> {
            JSONObject filterObj = (JSONObject) filter;
            String field = filterObj.getString("field");
            if ("location".equals(field)) {
                condi.put("locationId", filterObj.getJSONObject("value").getString("id"));
                condi.put("locationCompanyId", filterObj.getJSONObject("value").getJSONObject("company").getString("id"));
            } else if ("scene".equals(field)) {
                condi.put("sceneId", filterObj.getJSONObject("value").getString("id"));
            }
        });

        if (domain != null) { // 弹出框输入条件, 暂时只有一个
            JSONArray condition = getJO.getJSONArray("condition");
            if (!condition.isEmpty()) {
                condi.put("contractIdAndNameOrPartnerIdAndName", condition.getJSONObject(0).getString("value"));
            }
        } else if (group != null) { // 界面输入框
            condi.put("contractIdAndNameOrPartnerIdAndName", getJO.getString("key"));

        } else if (group == null && domain == null) { // ???什么操作会两个都为空

        }
        List<Contract> contracts = invoke("stock.replePurSumItemService.externalObtainContract", condi);
        Pageable pageable = PageRequest.of(getJO.getIntValue("page"), getJO.getIntValue("size"));
        PageImpl page = new PageImpl<>(contracts, pageable, contracts.size());

        return page;
    }
    public Page<Map> getContract2(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        JSONObject group = getJO.getJSONObject("group");
        JSONObject domain = getJO.getJSONObject("domain");

        String supplierId = "", companyId = "", sceneId = "";

        JSONArray filters = group != null?group.getJSONArray("filters"):domain != null?domain.getJSONArray("filters"):new JSONArray();
        for (int i = 0, iLen = filters.size(); i < iLen; i++) {
            JSONObject filterObj = filters.getJSONObject(i);
            if ("location".equals(filterObj.getString("field"))) companyId = filterObj.getJSONObject("value").getJSONObject("company").getString("id");
//            if ("company".equals(filterObj.getString("field"))) companyId = filterObj.getJSONObject("value").getString("id");
            if ("scene".equals(filterObj.getString("field"))) sceneId = filterObj.getJSONObject("value").getString("id");
        }
        if (group != null) supplierId = filters.getJSONObject(0).getString("value");
        if (domain != null) {
            String value = "";
            JSONArray condition = getJO.getJSONArray("condition");
            if (condition.size() != 0) {
                JSONObject conditionValue = condition.getJSONObject(0);
                value = conditionValue.getString("value");
            }
            value = "PO002".equals(sceneId)?"A00000":"PO003".equals(sceneId)?"004465":value;
            supplierId = value;
        } else if (group == null && domain == null) {
            supplierId = getJO.getString("id");
            companyId = getJO.getString("companyId");
            sceneId = getJO.getJSONObject("scene").getString("id");
        }
        List suppliers = new ArrayList();
        suppliers.add(supplierId);

        List notInSupplier = new ArrayList();
        notInSupplier.add("占位");
        if (!"PO002".equals(sceneId) && !"PO003".equals(sceneId)) {
            notInSupplier.add("004465");
            notInSupplier.add("A00000");
        }
        JSONObject condi = new JSONObject();
        condi.put("supplierId", suppliers);
        condi.put("companyId", companyId);
        condi.put("type", "purchaseOrder");
        condi.put("notinSupplier", notInSupplier);
        List contractList = new ArrayList();
        try {
            contractList = invoke("stock.replenishmentManagementService.thirdPartyQueryContract", condi);
        } catch (Exception e) {
        }
        Pageable pageable = PageRequest.of(getJO.getIntValue("page"), getJO.getIntValue("size"));
        PageImpl page = new PageImpl<>(contractList, pageable, contractList.size());
        return page;
    }

    /**
     * 根据系统变量取价格
     * @return
     */
    private JSONObject getPrice(SimpleRequest request) {
        String companyId = request.get("HTGSID");//取采购合同的公司id
        String productId = request.get("SPID");
        String supplierId = request.get("GYSID");
        // 获取价格
        JSONObject getJG = getPurcherPrice(companyId, supplierId, productId, "");
        double gP901 = getJG.getDoubleValue("P901");
        double gP904 = getJG.getDoubleValue("P904");
        double nakedPrice = "1007".equals(request.get("CGZZID").toString())?gP901:gP904;

        if (nakedPrice == 0) throw new RuntimeException("采购价格文件不能为0！商品编码：" + productId + " 供应商：" + supplierId);

        getJG.put("purchasePrice", nakedPrice);
        return getJG;
    }



    // 导入
    public JSONObject importInfo(SimpleRequest simpleRequest) {
        JSONObject importData = simpleRequest.get("importData"); // excel导入信息
        JSONArray columnName_Array = simpleRequest.get("data");
        JSONObject model = simpleRequest.getJO().getJSONObject("model");
        String sheetName = (String) importData.keySet().toArray()[0];

        JSONArray columnEnglish_Array = new JSONArray();
        columnEnglish_Array.add("product");
        columnEnglish_Array.add("priceCeiling");
        columnEnglish_Array.add("uom");
        columnEnglish_Array.add("productUomQty");
        columnEnglish_Array.add("effectiveQty");
        columnEnglish_Array.add("priceUnit");
        columnEnglish_Array.add("tax");
        columnEnglish_Array.add("priceTotal");
        columnEnglish_Array.add("priceSubtotal");
        columnEnglish_Array.add("priceTax");

        JSONObject returnData = new JSONObject();
        JSONArray returnData_Array = new JSONArray();
        //初始化价格文件查询条件
        String supplierId = model.getJSONObject("supplier").getString("id");
        String companyId = model.getJSONObject("company").getString("id");
        PartyRole company = partyRoleRepository.findOne(companyId);

        JSONObject accessProvider = invoke("cm.accessProvider.accordingCompanyAccessProvider", MapUtil.mapper("companyId", company.getId()));
        String accessProviderId = (accessProvider != null && accessProvider.size() != 0)?accessProvider.getString("vendorCode"):"";

        //查询价格文件
        importData.forEach((k, v) -> {
            JSONObject saveSigleData_Obj = new JSONObject();
            JSONArray item = (JSONArray) importData.get(k);
            JSONArray itemCloneArray = (JSONArray) item.clone();
            itemCloneArray.remove(0);
            List productIds = itemCloneArray.stream().filter(singleCloneA ->{return !((JSONArray) singleCloneA).isEmpty();}).map(singleCloneArray -> {

                return String.valueOf(((JSONArray) singleCloneArray).get(0)).trim();}).collect(Collectors.toList());
            JSONArray productIdArray = invoke("pi.piService.checkPriceExists", MapUtil.mapper("productIds", productIds, "supplier", supplierId,
                    "company",companyId,"accessProvider",accessProviderId));
            if (productIdArray != null && productIdArray.size() > 0) {
                String productId = "";
                for (int i = 0; i < productIdArray.size(); i++) {
                    productId += String.valueOf(productIdArray.get(i)).trim() + ";";
                    if (productId.length() > 110) productId += "\r\n";
                }

                throw new RuntimeException("请联系采购部门定义价格, 商品：\r\n" + productId);
            }

            judgeProductState(item);
            returnData_Array.add(0, columnEnglish_Array);
            for (int i = 0, iLen = item.size(); i < iLen; i++) {// 表头 和 明细数据
                if (i == 0) continue;
                JSONArray item_Array = (JSONArray) item.get(i); // 明细数据
                if (item_Array.isEmpty()) continue;
                JSONObject condition = new JSONObject();
                saveSigleData_Obj = new JSONObject();

                int count = 0;
                double productUomQty = 0;
                for (int j = 0, jLen = item_Array.size(); j < jLen; j++) {
                    if (j == 0) {
                        Product product = productRepository.findOne(item_Array.getString(j));
                        if (product == null) throw new RuntimeException("未匹配到对应的商品，商品编码：" + item_Array.getString(j));
                        condition.put("productId", product.getId());
                        condition.put("PLID", product.getClassify().getId());
                        condition.put("PPID", product.getBrand().getId());
                        condition.put("SPID", product.getId());
                        condition.put("JLDW", product.getUom().getName());
                        saveSigleData_Obj.put("product", product);
                        saveSigleData_Obj.put("uom", product.getUom());
                    } else {
                        productUomQty = ((Integer) item_Array.get(j)).doubleValue();
                        saveSigleData_Obj.put("productUomQty", item_Array.get(j));
                        saveSigleData_Obj.put("effectiveQty", saveSigleData_Obj.get("productUomQty"));
                    }
                }
                SimpleRequest requestCondition = new SimpleRequest();
                String deptId = model.getJSONObject("dept").getString("id");
                Dept dept = deptRepository.findOne(deptId);
                List<ContrastPartyCode> contrastPartyCode = contrastPartyCodeRepository.findAll(JpaDsl.toCriteriaByEq("party.id", model.getJSONObject("supplier").getJSONObject("party").getString("id")));
                if (contrastPartyCode.size() == 0) {
                    throw new RuntimeException("请配置角色对照表对应的供应商！");
                }
                condition.put("GYSID", contrastPartyCode.get(0).getGysid());
                if ("A1001".equals(contrastPartyCode.get(0).getGysid()) || "1001".equals(model.getJSONObject("company").getString("id"))) {
                    condition.put("SYGSID", "1001");
                    condition.put("CGZZID", "1001");
                } else {
                    condition.put("SYGSID", "1007");
                    condition.put("CGZZID", "1007");
                }
                condition.put("supplierId", supplierId);
                condition.put("companyId", companyId);
                condition.put("SCENE", model.getJSONObject("scene").getString("id"));

                // 获取税率
                requestCondition.setData(condition);
                Tax tax = taxService.getPurchaseTax(/*requestCondition*/partyRoleRepository.findOne(companyId), partyRoleRepository.findOne(supplierId), productRepository.findOne(requestCondition.get("SPID").toString()));
                saveSigleData_Obj.put("tax", tax);
                condition.put("taxId", tax.getId());

                // 获取价格
                String productId = requestCondition.get("SPID");
                JSONObject getJG = getPurcherPrice(companyId, supplierId, productId, ""); //输入车牌号，实现一车一价

                double gP901 = getJG.getDoubleValue("P901");
                if (gP901 == 0) {
                    throw new RuntimeException("采购价格文件不能为0！商品编码：" + requestCondition.get("SPID") + " 供应商：" + supplierId);
                }
                saveSigleData_Obj.put("priceUnit", gP901 + "");
                saveSigleData_Obj.put("priceTotal", productUomQty * gP901);
                saveSigleData_Obj.put("priceCeiling", getJG.getDoubleValue("P902"));
                condition.put("priceUnit", gP901 + "");
                condition.put("qty", productUomQty + "");


                // 计算税金
                Map getTaxAmount = taxService.computeTaxAmount(requestCondition);
                saveSigleData_Obj.put("priceTotal", getTaxAmount.get("totalIncluded"));
                saveSigleData_Obj.put("priceSubtotal", getTaxAmount.get("totalExcluded"));
                saveSigleData_Obj.put("priceTax", getTaxAmount.get("taxAmt"));
                returnData_Array.add(saveSigleData_Obj);
            }
        });
        returnData.put(sheetName, this.formatContent(sheetName, columnName_Array, returnData_Array));
        return returnData;
    }

    // 判断商品导入是否为停用
    private void judgeProductState(JSONArray importData) {
        Pattern p;
        Matcher m;
        String productIdStr = "";
        List<Product> errorProductIds = new ArrayList<>();
        for (int i = 1; i < importData.size(); i++) {
            if (importData.getJSONArray(i).size() == 0) continue;
            productIdStr += "'" + importData.getJSONArray(i).get(0) + "',";
            double number = i / 1000;
            p = Pattern.compile("[0-9]*");
            m = p.matcher("" + number);
            if (m.matches() || i == importData.size() - 1) {
                errorProductIds.addAll(productRepository.findAll("SELECT ID FROM MAS_PRODUCT WHERE ID IN (" + productIdStr.substring(0, productIdStr.length() - 1) + ") AND (STATE = '2' OR STATE = '3') "));
                productIdStr = "";
            }
        }
        if (errorProductIds.size() > 0) {
            throw new RuntimeException("停产下市、停用商品不可导入，请找替换产品采购！商品有" + errorProductIds.toString());
        }
    }


    // 导入 - 格式化内容
    private JSONArray formatContent(String sheetName, JSONArray columnName_Array, JSONArray returnData_Array) {
        String existsColumn = "";
        JSONArray existsDataColumn_Array = returnData_Array.getJSONArray(0);
        for (int j = 0, jLen = existsDataColumn_Array.size(); j < jLen; j++) {
            existsColumn += existsDataColumn_Array.get(j) + ",";
        }

        // 循环明细
        JSONArray returnDataList = new JSONArray();
        JSONArray webTitle = new JSONArray();

        JSONArray saveSingleData = new JSONArray();
        for (int i = 0, iLen = returnData_Array.size(); i < iLen; i++) {
            if (i == 0) continue;
            JSONObject returnData_Obj = returnData_Array.getJSONObject(i);
            saveSingleData = new JSONArray();

            for (int k = 0, kLen = columnName_Array.size(); k < kLen; k++) {
                String kName = columnName_Array.getJSONObject(k).getString("name");
                String kField = columnName_Array.getJSONObject(k).getString("field");
                if (i == 1) {
                    webTitle.add(k, kName);
                }
                if (existsColumn.indexOf(kField + ",") == -1) {
                    saveSingleData.add(k, "");
                } else {
                    saveSingleData.add(k, returnData_Obj.get(kField));
                }
            }
            if (i == 1) {
                returnDataList.add(webTitle);
            }
            returnDataList.add(saveSingleData);
        }
        return returnDataList;
    }


    public JSONObject formatCGDD(Pick pick, String cgddh) {
        String pCKKQID = pick.getLocation().getId();
        JSONObject returnData = new JSONObject();
        returnData.put("CGDDH", cgddh);
        JSONArray CGDDMX_Array = new JSONArray();
        JSONObject Single_CGDDMX = new JSONObject();
        for (PickItem pickItem : pick.getPickItems()) {
            Single_CGDDMX.put("CKKQID", pCKKQID);
            Single_CGDDMX.put("SPID", pickItem.getProduct().getId());
            Single_CGDDMX.put("RKJS", pickItem.getQtyDone());
            Single_CGDDMX.put("HSBL", pickItem.getUom().getFactor());
            CGDDMX_Array.add(Single_CGDDMX);
            Single_CGDDMX = new JSONObject();
        }
        returnData.put("PUR_CGDDMX", CGDDMX_Array);
        return returnData;
    }

    /**
     * 根据单号、外部单号找订单
     * @param simpleRequest
     * @param <T>
     * @return
     */
    public <T> T accordinNumberFind(SimpleRequest simpleRequest) {
        String[] customCondition = {"id", "EQ", "value", "origin", "EQ", "value", "supplierRef", "EQ", "value", "source", "EQ", "value", "productRequire", "EQ", "value", "externalDocument", "EQ", "value"};

        JSONObject getJO = simpleRequest.getJO();
        String excludesFields = "无".equals(getJO.getString("excludesFields"))?"":"purchaseItems";
        Object obj = queryCommonService.accordinNumberFindLogic(simpleRequest, orderRepository, customCondition, "id", excludesFields);
        if ("java.util.HashMap".equals(obj.getClass().getName())) {
            return (T) obj;
        }
        Page page = queryCommonService.accordinNumberFindLogic(simpleRequest, orderRepository, customCondition, "id", excludesFields);
        if (page.getContent() != null && page.getContent().size() != 0) {
            PurchaseOrder order = ((PurchaseOrder) page.getContent().get(0));
            this.sortOrderItem(order.getPurchaseItems());
        }
        return (T) page;
    }

    // 采购订单明细排序
    private void sortOrderItem(List<PurchaseOrderItem> orderItems) {
        Collections.sort(orderItems, (PurchaseOrderItem o1, PurchaseOrderItem o2) -> {
            String classifyId1 = o1.getProduct().getClassify().getId();
            String classifyId2 = o2.getProduct().getClassify().getId();
            String brandId1 = o1.getProduct().getBrand().getId();
            String brandId2 = o2.getProduct().getBrand().getId();
            String mergeStr1 = classifyId1 + "" + brandId1;
            String mergeStr2 = classifyId2 + "" + brandId2;
            return mergeStr1.compareTo(mergeStr2);
        });
    }

    /***
     * 关联采购单号 上游单号 第三方单号 原始单号进行查询
     * 一般情景不建议使用
     */
    public Page<PurchaseOrder> findAllRelate(SimpleRequest request) {
        Group group = findAllCore(request);
        return orderRepository.findAll(group.build(true), JpaDsl.getPageable(request));
    }

    /***
     * 默认传入权限
     */
    public List<PurchaseOrder> findAllRelateNoPage(SimpleRequest request) {
        Group group = findAllCore(request);
        return orderRepository.findAll(group.build(true));
    }


    /***
     * 抽取的公共逻辑
     */
    private Group findAllCore(SimpleRequest request) {
        Group group = JpaDsl.getGroup(request);

        List<Filter> filters = group.getFilters();

        // 筛选出对应的id， 用于匹配 第三方单号 原始单号 上游单号
        Filter filter = filters.stream().filter(item -> item.getField().equals("id")).findFirst().orElse(null);

        if (filter != null) {
            filters.remove(filter); // 移除当前选项

            Group idGroup = new Group();
            idGroup.setOperator("or");
            idGroup.addFilters(JpaDsl.toFilter(
                    "supplierRef", "EQ", filter.getValue(),
                    "id", "EQ", filter.getValue(),
                    "source", "EQ", filter.getValue(),
                    "origin", "EQ", filter.getValue(),
                    "externalDocument", "EQ", filter.getValue()
            ));
            group.addGroup(idGroup);
        }

        // 删除数据不选出来
        filter = new Filter();
        filter.setField("state");
        filter.setValue("delete");
        filter.setOperator("NE");
        filters.add(filter);
        return group;
    }

    @OutboxSubscriber(id = "local:PurchaseService.updateOldRKSL", name = "修改老框架采购入库数量")
    public void updateOldRKSL(OutboxPayloadWrapper outboxPayloadWrapper) {
        piManager.synErp("scmCgddService.updateCGDDRKSL", outboxPayloadWrapper.getPayload());
    }

    public SupplierShipItem getSupplierShipItem(SimpleRequest request) {
        String supplierId = request.getJO().getString("supplierId");
        SupplierLogisticRepository supplierLogisticRepository = SpringManager.getBean(SupplierLogisticRepository.class);
        List<SupplierLogistic> supplierLogistics = supplierLogisticRepository.findAll(JpaDsl.toCriteriaByEq("supplier.id", supplierId));
        if (supplierLogistics.size() == 0) return null;
        return supplierLogistics.get(0).getSupplierShipItems().get(0);
    }

    public void setSuppliterInformation(PurchaseOrder purchaseOrder) {
        if (purchaseOrder.getSupplierShipItem() == null && purchaseOrder.getContract() != null) {
            SupplierLogisticRepository supplierLogisticRepository = SpringManager.getBean(SupplierLogisticRepository.class);
            List<SupplierLogistic> supplierLogistics = supplierLogisticRepository.findAll(JpaDsl.toCriteriaByEq("supplier", purchaseOrder.getContract().getPartner()));
            if (supplierLogistics.size()==1 && supplierLogistics.get(0).getSupplierShipItems().size()==1) {
                SupplierShipItem supplierShipItem = supplierLogistics.get(0).getSupplierShipItems().get(0);
                purchaseOrder.setSupplierShipItem(supplierShipItem);
                purchaseOrder.setContact(supplierShipItem.getContact());
                purchaseOrder.setPhone(supplierShipItem.getPhone());
            }

        }
    }

    public List getContractByScene(SimpleRequest request) {
        JSONObject jo = request.getJO();
        String scene = jo.getString("scene");
        String locationId = jo.getString("locationId");
        Location location = SpringManager.getBean(LocationRepository.class).findOne(locationId);
        String operation = location.getCompany().getParty().getCorporate().getOperation().getId();
        String str = "PO002".equals(scene)?"期初采购合同/协议":"现金采购合同/协议";
        if ("001073".equals(operation)) {
            boolean result = invoke("fn.contract.checkFnCompany", mapper("companyId", location.getCompany().getId()));
            if (!result) throw new RuntimeException("此赋能公司未签赋能合同，请核实！");
            List<Contract> contractList = contractRepository.findAll(JpaDsl.toCriteria(
                    "cooperation.id","EQ","distribution",
                    "state","EQ","approve",
                    "contractType.code","IN",Arrays.asList("supplier","platform"),
                    "company.id","EQ","1007",
                    "partner.id","EQ","PO002".equals(scene)?"A00000":"004465",
                    "validPeriod","GT",new Date()
            ));
            if (contractList.size() == 0) throw new RuntimeException("未找到有效的" + ("PO002".equals(scene)?"A00000":"004465") + "供应商的" + str);
            return contractList;
        }else {
            List<Contract> contractList = contractRepository.findAll(JpaDsl.toCriteria(
                    "state","EQ","approve",
                    "contractType.code","IN",Arrays.asList("supplier","platform"),
                    "company.id","EQ",location.getCompany().getId(),
                    "partner.id","EQ","PO002".equals(scene)?"A00000":"004465",
                    "validPeriod","GT",new Date()
            ));
            if (contractList.size() == 0) throw new RuntimeException("未找到有效的" + ("PO002".equals(scene)?"A00000":"004465") + "供应商的" + str);
            return contractList;
        }
    }

    public void findSiteAndAdress(PurchaseOrder order) {
        if(order.getPurchasingGroup() != null) {
            JSONObject object = invoke("cm.purchasingGroup.findPurchaseOrderSite",mapper("purchasingGroupId",order.getPurchasingGroup(),"locationId",order.getLocation().getId()));
            if (object.getString("siteName") != null) order.setSiteName(object.getString("siteName"));
            if (object.getString("siteId") != null) order.setSiteId(object.getString("siteId"));
            if (object.getString("phyDepotAddress") != null) order.setAdress(object.getString("phyDepotAddress"));
        }
    }

    public String getModel(SimpleRequest request) {
        return SpringManager.getBean(CrossTransferVoucherBuilder.class).getModel(partyRoleRepository.findOne(request.get("companyId").toString()));
    }

    // 老系统询价单获取价格
    public Object getPriceCG03(SimpleRequest request) {
        Map map = request.getMap();
        map.put("P001", map.get("newP001"));
        map.put("CLASSIFY_ID", map.get("PLID"));
        map.put("BRAND_ID", map.get("PPID"));
        map.put("conditionStrategyId", "CG03");
        map.put("SYS_RQ", new Date());
        return this.invoke("condition.execConditionStrategy", map);
    }

    /*
    * 巴图鲁发货生成交货单
    * 注意：1. 需要考虑是否把巴图鲁发货来的数据存储到 mongo
    * 2. 是否会有一个商品多次发货的情况
    * */
    public void generatePick_baturu(SimpleRequest request) {
        if (true) return; // 巴图鲁发货有问题，等修复后放开，先跟正常采购一样创建交货单
        JSONObject getJO = request.getJO();
        this.saveBaturuNotice("巴图鲁生成交货单", getJO);
        JSONObject data = getJO.getJSONObject("data");
        String trackingNumber = data.getJSONObject("logisticsInfo").getString("trackingNumber");
        String supplierId = String.valueOf(data.getLongValue("supplierId"));
        String supplierName = String.valueOf(data.getString("supplierName"));
        JSONArray orderDetailList = data.getJSONArray("orderDetailList");

        PurchaseOrder pOrder = orderRepository.findAll(JpaDsl.toCriteriaByEq("supplierRef", data.getString("orderNo"))).stream().findFirst().orElse(null);
        List<Map> picks = SpringManager.getBean(PickRepository.class).accordParcelListNoFind(trackingNumber, pOrder.getId());
        if (!picks.isEmpty()) return;
        if (ObjectUtils.isEmpty(pOrder)) throw new RuntimeException("未找到对应采购订单");
        List<Map> priceNos = new ArrayList();
        orderDetailList.forEach(orderDetail -> {
            JSONObject orderDetailObj = (JSONObject) orderDetail;
            priceNos.add(MapUtil.mapper(orderDetailObj.getString("priceNo"), orderDetailObj.getInteger("num")));
        }); // 查看过滤保存是否会影响明细

        List eligibleData = new ArrayList();
        pOrder.getPurchaseItems().forEach(purchaseItem -> {
            priceNos.stream().forEach(priceNo -> {
                Map priceNoM = (Map) priceNo;
                if (priceNoM.containsKey(purchaseItem.getExternalCode())) {
                    eligibleData.add(purchaseItem);
                }
            });
        });

        JSONObject otherInfo = new JSONObject(MapUtil.mapper("trackingNumber", trackingNumber, "supplierId", supplierId, "supplierName", supplierName, "priceNos", priceNos));
        invoke("stock.pick.create", MapUtil.mapped(purchaseConverPick(pOrder, eligibleData,  otherInfo)));
    }

    public void cancelPurchaseOrder_baturu(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        this.saveBaturuNotice("巴图鲁取消采购订单", getJO);
        JSONObject data = getJO.getJSONObject("data");
        JSONArray orderDetailList = data.getJSONArray("orderDetailList");
        PurchaseOrder pOrder = orderRepository.findAll(JpaDsl.toCriteriaByEq("supplierRef", data.getString("orderNo"))).stream().findFirst().orElse(null);
        if (pOrder == null) return;
        PurchaseOrderItem canCancelItem = pOrder.getPurchaseItems().stream().filter(item -> item.getProductUomQty() != (item.getQtyReceived() + item.getStopQty())).findFirst().orElse(null);
        if (canCancelItem == null) return;
        orderDetailList.forEach(orderDetail -> {
            JSONObject orderDetailObj = (JSONObject) orderDetail;
            double cancelNum = orderDetailObj.getDoubleValue("cancelNum");
            pOrder.getPurchaseItems().forEach(pItem -> {
                if (orderDetailObj.getString("priceNo").equals(pItem.getExternalCode())) {
                    double cancelQty = pItem.getProductUomQty() - pItem.getQtyReceived() - pItem.getStopQty();
                    double canCancelQty =  pItem.getQtyReceived() == 0?cancelNum: cancelQty > cancelNum?cancelNum:cancelQty;
                    if (canCancelQty <= 0) return;
                    pItem.setEffectiveQty(cancelNum);
                    pItem.setStopQty(cancelNum);
                }
            });
        });
        pOrder.setState("cancel");
        pOrder.setDateCancel(new Date());
        pOrder.setCancelNameId(partyRoleRepository.findOne("system")); // 待定
        this.baturuCancelOrder(pOrder, orderDetailList);
        //invoke("sp.baturuCodingService.baturuEndOrder",MapUtil.mapper("data",data));
    }

    public void saveBaturuNotice(String type, JSONObject content) {
        Document column = new Document();
        column.putAll(MapUtil.mapper("type", type, "content", content));
        column.put("currentDate", DateUtil.format(new Date(), DateUtil.SHOW_DATE_FORMAT));
        mongoTemplate.getCollection("baturu_notice").insertOne(column);
    }

    // 【审核】生成要货扩展表、减少订货数量、增加分配数量
    private void confirmUpdateRequireOrderQtyAndExpand(PurchaseOrder order) {
        if (!StringUtils.isEmpty(order.getSupplierType()) && LogicalUtil.in(order.getSupplierType(), "santou", "supplier")) return;
        if (StringUtils.isEmpty(order.getProductRequire())) return;
        List<Map> requireDatas = new ArrayList<>();
        order.getPurchaseItems().forEach(item -> {
            if (StringUtils.isEmpty(item.getSourceItemId())) return;

            ProductUom requireUom = this.obtainRequireUomId(item.getSourceItemId());
            JSONObject requireAllQty = this.obtainRequireQty(item);
            double orderQty = item.getProductUomQty();
//            if (item.getUom().getId() != requireUom.getId()) {
//                orderQty = this.purchaseUomConvertRequireUomQty(requireUom.getId(), item.getUom(), item.getProductUomQty());
//            }

            // 减少要货数量
//            productAccountService.setProductRequireBilling(item.getProduct(), order.getLocation(), requireUom, -1 * orderQty,
//            order.getInnerBusinessType(), order.getId(), String.valueOf(item.getId()), "采购审核", order.getLocation().getCompany(), order.getProductRequire());


            // 变更库存要货制单数量, ********【必须先修改要货制单数量，再修改要货分配数量】*********
            invoke("stock.productRequireService.currentAssigentQty",
                    MapUtil.mapper(
                            "requireItemId", item.getSourceItemId(), "uomId", item.getUom().getId(), "qty", item.getProductUomQty(),
                            "operateId", order.getId(), "operateBusinessType", order.getInnerBusinessType(), "operateItemId", item.getId(),
                            "operateRemark", "采购订单审核"
                    ));

            // 生成要货扩展表
            this.sendRequireExpandData(order.getProductRequire(), order.getId(), order.getSourceType(), item, requireAllQty.getDoubleValue("qtyRequire"));

            // 拼接要货数据
            requireDatas.add(MapUtil.mapper("orderQty", -1 * orderQty, "qtyAssigned", orderQty, "id", item.getSourceItemId()));
        });
        if (requireDatas.isEmpty()) return;
        invoke("stock.productRequireService.updateAssignmentQtyAndOrderQty", MapUtil.mapper("id", order.getProductRequire(), "distributionId", order.getId(), "item", requireDatas));
    }

    // 【终止】生成要货扩展表 减少分配数量
    private void cancelUpdateRequireOrderQtyAndExpand(PurchaseOrderItem orderItem) {
        PurchaseOrder order = orderItem.getPurchaseOrder();
        if (StringUtils.isEmpty(order.getProductRequire()) || StringUtils.isEmpty(orderItem.getSourceItemId())) return;

        String distributionId = "supplier".equals(order.getSupplierType())?order.getSupplierRef():order.getId();

        //  1. 修改要货扩展表
        Map requireExpand = MapUtil.mapper("distributionId", distributionId, "originItemId", orderItem.getSourceItemId(), "cancelQty", orderItem.getStopQty());
        invoke("stock.productRequireExpandService.updateCancelQty", requireExpand);


        // 2. 减少要货数量 *******************【先变更库存要货制单数量，再修改要货分配数量】*************************
        invoke("stock.productRequireService.currentStopQty",
                MapUtil.mapper(
                        "requireItemId", orderItem.getSourceItemId(), "uomId", orderItem.getUom().getId(), "qty", orderItem.getStopQty(),
                        "operateId", order.getId(), "operateBusinessType", order.getInnerBusinessType(), "operateItemId", orderItem.getId(),
                        "operateRemark", "采购订单终止"
                ));

        // 3. 拼接要货数据
        List<Map> requireDatas = new ArrayList<>();
        requireDatas.add(MapUtil.mapper( "qtyAssigned", -1 * orderItem.getStopQty(), "id", orderItem.getSourceItemId()));
        if (requireDatas.isEmpty()) return;
        invoke("stock.productRequireService.updateAssignmentQty", MapUtil.mapper("id", order.getProductRequire(), "distributionId", distributionId, "item", requireDatas));
    }


    // 【修改】发送修改要货订货数量请求
    private void UpdateRequireQty(PurchaseOrder order, double operator) {
        if (StringUtils.isEmpty(order.getProductRequire())
                || !"要货补货管理-采购".contains(Objects.isNull(order.getNote())?"":order.getNote())
                || "CD0".equals(order.getSourceType())
                || "santou".equals(order.getSupplierType())
                || "supplier".equals(order.getSupplierType())) return; // 需要限定为要货补货管理-采购的数据，其他逻辑还没修改????????????????????

        List<Map> requireData = new ArrayList<>();
        order.getPurchaseItems().forEach(item -> {
            ProductUom requireUom = this.obtainRequireUomId(item.getSourceItemId());
            double orderQty = item.getProductUomQty();
            if (item.getUom().getId() != requireUom.getId()) {
                orderQty = this.purchaseUomConvertRequireUomQty(requireUom.getId(), item.getUom(), item.getProductUomQty());
            }

            // 拼接要货数据
            requireData.add(MapUtil.mapper("id", item.getSourceItemId(), "qty", operator * orderQty));
        });
        if (requireData.isEmpty()) return;
        this.sendSynEvent("event:server.productRequireService.updateOrderQty", MapUtil.mapper("id", order.getProductRequire(), "item", requireData));
    }

    // 获取要货单位
    private ProductUom obtainRequireUomId(String requireItemId) {
        long requireUomId = invoke("stock.productRequireService.findRequireUom", MapUtil.mapper("id", requireItemId));
        if (requireUomId == -1L) throw new RuntimeException("根据要货明细编码未找到有效要货计量单位！");
        return productUomRepository.findOne(requireUomId);
    }

    // 根据要货计量单位转换数量
    private double purchaseUomConvertRequireUomQty(long requireUomId, ProductUom currentOrderUom, double qty) {
        ProductUom requireUom = productUomRepository.findOne(requireUomId);
        return currentOrderUom.computeQty(qty, requireUom, true);
    }

    // 获取要货数量
    private JSONObject obtainRequireQty(PurchaseOrderItem item) {
        List requireQty = sendSynEvent("event:service.productRequireService.findRequireQty", MapUtil.mapper("id", item.getSourceItemId()));
        if (requireQty.isEmpty()) throw new RuntimeException("根据要货明细编码有效要货明细！");
        return (JSONObject) requireQty.get(0);
    }


    // 写入要货扩展表
    private void sendRequireExpandData(String requireId, String distributionId, String originBusinessType, PurchaseOrderItem orderItem, double requireQty) {

        double qty = orderItem.getProductUomQty();
        Map requireExpand = MapUtil.mapper("distributionId", distributionId,
                "origin", requireId,
                "originBusinessType", originBusinessType,
                "originItemId", orderItem.getSourceItemId(),
                "productUomId", MapUtil.mapper("id", orderItem.getUom().getId()),
                "requireQty", requireQty,
                "assignQty", qty,
                "productId", MapUtil.mapper("id", orderItem.getProduct().getId()));

        // 写入要货扩展表
        invoke("stock.productRequireExpand.save", requireExpand);
    }

    private boolean judgeStatisfyUpdateOtherTableCond(PurchaseOrder order)  {
        if (StringUtils.isEmpty(order.getProductRequire()) || !"要货补货管理-采购".contains(order.getNote()) ||
                "CD0".equals(order.getSourceType())) return true;
        return false;
    }


    @Listener(topic = "event:scm.purchaseService.accordItemIdFindSourceItemId")
    public String accordItemIdFindSourceItemId(SimpleRequest request) {
        PurchaseOrderItem item = purchaseOrderItemRepository.findOne(request.getJO().getLong("id"));
        return item.getSourceItemId();
    }

    @Listener(topic = "event:scm.purchaseService.accordIdFind")
    public JSONObject accordIdFind(SimpleRequest request) {
        PurchaseOrder order = orderRepository.findOne(request.getJO().getString("id"));
        if (Objects.isNull(order)) return new JSONObject();
        return new JSONObject(MapUtil.mapper("productRequire", order.getProductRequire()));
    }

    public JSONObject findThirdId(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        if ("PurchaseOrder".equals(getJO.getString("originBusinessType"))) {
            PurchaseOrder order = orderRepository.findOne(getJO.getString("origin"));
            if ("巴图鲁采购订单".equals(order.getSupplierType())) { // 巴图鲁切换到供应商平台以后可以直接使用 else
                getJO.put("thirdId", order.getSupplierRef());
            } else {
                getJO.put("thirdId", order.getExternalDocument());
            }

        }
        return getJO;
    }


    public JSONObject printOne(SimpleRequest request) {
        String id = request.getJO().getString("id");
        PurchaseOrder crossCompanyTransferNew = orderRepository.findOne(request.getJO().getString("id"));
        List<PurchaseOrderItem> crossItemNews = purchaseOrderItemRepository.findTransferId(id);
        JSONObject crossNew = new JSONObject();
        Map main = MapUtil.mapped(crossCompanyTransferNew);
        main.remove("purchaseItems");

        List<Map> crossItems = MapUtil.mapped(crossItemNews);
        for (int i = 0, iLen = crossItems.size(); i < iLen; i++) {
            Map singleCrossItem = crossItems.get(i);
            singleCrossItem.put("XH", i+1);
        }
        main.put("purchaseItems", crossItems);

        crossNew.putAll(main);
        return crossNew;
    }

}

























